iT邦幫忙

2023 iThome 鐵人賽

DAY 16
0
Modern Web

自己開發一個~?系列 第 16

Springboot~開始設計表單

  • 分享至 

  • xImage
  •  

中秋節 雖然過了~還是有feel一樣快樂~
/images/emoticon/emoticon01.gif

package com.tzu2.controllers;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import javax.servlet.http.HttpServletRequest;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.tzu2.domain.Member;

//有關於會員操作的控制器Controller
@Controller
@RequestMapping(path="/member")
public class MemberController {
 //注入依賴物件DataSource
 @Autowired
 private DataSource datasource;
 
 
 //註冊Action(Method)
 @RequestMapping(path="/register",method= {RequestMethod.GET,RequestMethod.POST})
 public String register(@RequestParam(name="username")String userName
   ,String password,String email
   ,@RequestParam(name="realname")String realName) {
  //如何判斷傳送方式採用GET(直接調用表單頁面) or POST(進行會員註冊作業 資料???)
  System.out.println("register..."+userName);
  //直接調用表單頁面(註冊表單)
  return "memberregister";
 }
 //採用表單傳遞欄位進來之後 自動封裝到一個物件屬性去
 //註冊Action(Method)
 //參數按照型別 注入Injection該型別的物件
 //透過方法注入Servlet api-HttpServletRequest 
  @RequestMapping(path="/registerform",method= {RequestMethod.GET,RequestMethod.POST})
  public String registerForm(Model model,Member member) {
   //透過注入的依賴DataSource生產一個連接物件(連接上資料庫伺服器)
   String message=null;
   if(member.getUsername()!=null && member.getPassword()!=null) {
    Connection connection=null;
    try {
     connection=datasource.getConnection();
     System.out.println("資料庫:"+connection.getCatalog());
     //借助Jdbc進行會員註冊作業
     String sql="Insert Into webmember(username,password,email,realname,phone) values(?,?,?,?,?)";
     //1.透過連接物件取出命令物件 配置新增SQL
     PreparedStatement st=connection.prepareStatement(sql);
     //2.設定參數
     st.setString(1,member.getUsername());
     st.setString(2, member.getPassword());
     st.setString(3, member.getEmail());
     st.setString(4, member.getRealname());
     st.setString(5, member.getPhone());
     
     //3.完成新增作業
     int affect=st.executeUpdate();
     
     message="註冊成功!!!";
     //4.設定訊息
    } catch (SQLException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
     //設定狀態訊息
     message="會員名稱有問題!註冊失敗!!";
    }finally {
     //例外也好 正常也好 都要來這裡執行
     if(connection!=null) {
      //有開啟 進行關閉 將連接收集到Connection Pooling
      try {
       connection.close();
      } catch (SQLException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }
     }
    }
    //要進行狀態持續 借助Model進行狀態持續 也就Thymeleaf template
    model.addAttribute("message", message);
    model.addAttribute("member", member);
    //如何判斷傳送方式採用GET(直接調用表單頁面) or POST(進行會員註冊作業 資料???)
    System.out.println("register..."+member.getUsername());
   }
   //直接調用表單頁面(註冊表單)
   //帶整個member到畫面渲染
   return "memberregister";
  }

}

這是一個Spring MVC控制器的Java類,負責處理會員註冊相關的操作。讓我們來分解這段程式碼的關鍵部分:

  1. @Controller:此註解表示這是一個Spring MVC控制器,用於處理HTTP請求。

  2. @RequestMapping:這是類層級的@RequestMapping註解,設置了基本路徑,即/member。這表示該控制器處理的所有請求路徑都以/member開頭。

  3. @Autowired:此註解用於將DataSource依賴項注入到控制器中。DataSource通常用於數據庫連接。

  4. register 方法:這個方法處理/member/register路徑的GET和POST請求。它接受usernamepasswordemailrealName 作為參數,並返回"memberregister"視圖。然而,該方法目前僅輸出一條訊息,而不執行任何會員註冊操作。

  5. registerForm 方法:這個方法處理/member/registerform路徑的GET和POST請求。它接受一個Model對象和一個Member對象作為參數。這個方法的主要功能包括:

    • 嘗試建立與數據庫的連接。
    • 準備SQL語句,用於將會員註冊信息插入到數據庫中。
    • 設定SQL語句的參數,以使用Member對象的屬性。
    • 執行SQL語句並獲得受影響的行數。
    • 根據執行結果設定一條註冊訊息,並將其添加到Model中,以供視圖顯示。
  6. 最後,return "memberregister" 用於返回名為"memberregister"的視圖,並將註冊訊息和 Member 對象傳遞給視圖,以供顯示。

總之,這個控制器用於處理會員註冊操作。當用戶訪問/member/register/member/registerform路徑時,該控制器處理相應的請求,接收用戶輸入的註冊信息,並在數據庫中執行註冊操作。然後,它返回一個視圖,並在視圖中顯示註冊結果訊息。

package com.tzu2.domain;

public class Member implements java.io.Serializable {
	//Attribute
	private String username;
	private String password;
	private String realname;
	private String email;
	private String phone;
	public String getPhone() {
		return phone;
	}
	public void setPhone(String phone) {
		this.phone = phone;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getRealname() {
		return realname;
	}
	public void setRealname(String realname) {
		this.realname = realname;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}

}

前端程式碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>註冊作業</title>
</head>
<body>
<fieldset>
<legend>註冊作業</legend>
<!--設計表單-->
<form method="post">
    
    <div>
        <div>使用者帳號</div>
        <input type="text" th:value="${member.username}" name="username"/>
    </div>
    
    <div>
        <div>使用者密碼</div>
        <input type="password" th:value="${member.password}" name="password"/>
    </div>
    <div>
        <div>真實姓名</div>
        <input type="text" th:value="${member.realname}" name="realname"/>
    </div>
    <div>
        <div>EMAIL</div>
        <input type="text" th:value="${member.email}" name="email"/>
    </div>
    <div>
        <div>連絡電話</div>
        <input type="text" th:value="${member.phone}" name="phone"/>
    </div>
    <br/>
    <input type="submit" value="註冊"/>
</form>
<div><h3 th:text="${message}"></h3></div>
</fieldset>
</body>
</html>

這是一個HTML表單,用於註冊作業的網頁。以下是HTML代碼的主要組件:

  1. <meta> 標籤:用於定義網頁的字符集和瀏覽器相容性。

  2. <title> 標籤:設置網頁的標題,顯示在瀏覽器的標題欄中。

  3. <fieldset><legend>:用於組織和標題化表單元素,提供結構性信息。

  4. <form> 標籤:定義HTML表單,並使用 "post" 方法來提交表單數據。

  5. <input> 元素:用於輸入數據。

    • type="text"<input> 元素用於輸入文本數據,例如使用者帳號、真實姓名、EMAIL和連絡電話。
    • type="password"<input> 元素用於輸入密碼數據,例如使用者密碼。
  6. th:value="${member.xxx}":這些屬性用於使用Thymeleaf模板引擎,以將後端的member物件的屬性值填充到對應的 <input> 元素中,實現數據的預填充。

  7. <br/>:用於插入斷行,創建間距。

  8. <input type="submit">:提交表單的按鈕,用戶點擊後提交表單數據。

  9. <h3> 標籤:顯示註冊後的訊息,使用Thymeleaf的 th:text 屬性將後端的 message 填充到 <h3> 標籤中。

這個HTML表單可用於註冊使用者,使用者可以填寫帳號、密碼、真實姓名、EMAIL和連絡電話,然後點擊"註冊"按鈕提交數據。網頁上方的 <title> 標籤設置了網頁的標題為"註冊作業"。

測試http://localhost:8080/member/registerform
https://ithelp.ithome.com.tw/upload/images/20231102/201190353rX04ZxDzV.png

增加一個檔案:CustomersController

package com.tzu.controllers;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping(path="/customers")
public class CustomersController {
 //Attribute(Data Field) Field Injection
 
 //查詢功能設計
 @RequestMapping(path="/qry/country",
   method= {RequestMethod.GET,RequestMethod.POST})
 public String customersQry(String country) {
 return "customersqrycountry";
}
}

這是一個 Spring MVC 控制器,處理有關顧客的查詢功能。以下是控制器中的一些關鍵點:

  1. @Controller:這個註解標記類別為Spring MVC控制器,告訴Spring這個類別包含處理HTTP請求的方法。

  2. @RequestMapping:這個註解用於指定控制器處理的請求路徑的前綴,也就是當URL以 "/customers" 開頭時,這個控制器會處理相關的請求。

  3. customersQry 方法:這是一個處理查詢的方法,它處理 /customers/qry/country 路徑的 GET 和 POST 請求。當使用者發出這個請求時,該方法會接受一個名為 "country" 的參數。

    • String country:這個方法的參數 country 用於接收用戶在請求中提供的國家參數。
  4. 方法返回值:這個方法返回一個字符串 "customersqrycountry"。通常,這表示控制器將渲染名為 "customersqrycountry" 的視圖(View)。這個視圖是一個HTML模板或JSP文件,用於呈現查詢國家的結果。

總之,這個控制器設計用於處理有關顧客查詢國家的請求,它接受國家作為參數,然後可能將結果顯示在相應的視圖上。需要確保有一個名為 "customersqrycountry" 的視圖模板,以便它可以正確呈現查詢的結果。

再增加一個html檔

當然也是要用VSCODE編輯~然後再同步到後端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>客戶資料查詢</title>
</head>
<body>
    <!--表單頁面-->
    <form method="post">
        <div>國家別</div>
        <input type="text" name="country" th:value="${country}"/>
        <input type="submit" value="查詢"/>
    </form>
</body>
</html>

測試看看http://localhost:8080/customers/qry/country

這是一個 HTML 表單頁面,用於接受客戶查詢的國家別。以下是這個表單頁面的關鍵點:

  1. form 標籤:表單的起始標籤,使用 method="post" 來指定當用戶提交表單時將使用 POST 請求。

  2. input 標籤:用於接受用戶輸入的國家別。這個 input 元素的 name 屬性為 "country",這對應到控制器方法 customersQry 中的參數名稱。

  3. th:value="${country}":這個屬性表示使用Thymeleaf模板引擎來填充 input 元素的值。${country} 是Thymeleaf的變數,它將由控制器方法設定,然後填充到這個 input 元素中。

  4. input 標籤(第二個):這是一個提交按鈕,用戶可以點擊它來提交表單。

這個表單頁面用於接受用戶輸入的國家別,然後當用戶點擊 "查詢" 按鈕時,表單的內容將以 POST 請求的形式傳遞給相應的控制器方法。該控制器方法將處理查詢操作,並可能返回相關的結果。

希望成功~

先講解資料庫裏面是有view資料表

SQL VIEW 檢視表 / 視圖 - SQL 語法教學 Tutorial
View 是藉由 SQL SELECT 查詢動態組合生成的資料表 (亦即 View 是由查詢得到的結果集組合而成的資料表)。View 內的資料紀錄是由其它實際存在的資料表中產生的,它就像是一個虛擬資料表,實際上資料庫 (或說是硬碟)…
www.fooish.com

先試著創建~

先有一個table

CREATE TABLE `customer` (
  `ID` varchar(30) NOT NULL,
  `name` varchar(30) NOT NULL,
  `address` varchar(45) NOT NULL,
  `zipcode` varchar(45) NOT NULL,
  `phone` varchar(45) NOT NULL,
  `city` varchar(45) NOT NULL,
  `country` varchar(45) NOT NULL,
  `notes` varchar(45) NOT NULL,
   `SID` varchar(45) NOT NULL,
  
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='國家資料表';

創建等等要用的view資料表

CREATE  VIEW  customer_list 
AS SELECT ID,name,address,zipcode,phone,city,country,notes,SID
FROM customer;

先在裡面填入資料

也試著view查詢

Select * From customer_list Where country='Taiwan'

再改一下前端程式碼增加POST

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>客戶資料查詢</title>
</head>
<body>
    <!--表單頁面-->
    <form method="post">
        <div>國家別</div>
        <input type="text" name="country" th:value="${country}"/>
        <input type="submit" value="查詢"/>
    </form>
</body>
</html>

這是一個 HTML 表單頁面,用於接受客戶的國家別查詢。以下是這個表單頁面的要點:

  1. form 標籤:這是表單的起始標籤,它指定了使用 POST 方法提交表單。

  2. input 標籤:這個 input 元素用於接受用戶輸入的國家別。name 屬性為 "country",這個名稱將在後端控制器中用於識別該輸入字段。

  3. th:value="${country}":這是Thymeleaf模板引擎的語法,用於填充 input 元素的值。${country} 是一個Thymeleaf變數,它將由後端控制器設置,並將其值填充到這個 input 元素中。

  4. 第二個 input 標籤:這是提交按鈕,用戶可以點擊它來提交表單。

總之,這個表單允許用戶輸入國家別,當他們點擊 "查詢" 按鈕時,表單將被提交到後端控制器進行處理,以執行相關的查詢操作。表單中的 th:value 屬性確保在頁面首次載入時,如果有任何舊的查詢值,它們將被填充到輸入框中,以供用戶參考或修改。

後端程式碼:

package com.tzu.controllers;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping(path="/customers")
public class CustomersController {
 //Attribute(Data Field) Field Injection
 
 //查詢功能設計
 @RequestMapping(path="/qry/country",
   method= {RequestMethod.GET,RequestMethod.POST})
 public String customersQry(String country) {
  //是否第一次請求 沒有傳遞國家別
    if(country==null) {
     return "customersqrycountry"; //View Page名稱
    }else {
     System.out.println("查詢國家別:"+country);
  
  return "customersqrycountry";
}
 }
}

CustomersController 中的 customersQry 方法負責處理客戶查詢國家別的功能。以下是方法的關鍵點:

  1. @RequestMapping 注解:這個注解指定了處理這個方法的請求路徑,即 /customers/qry/country,並且指定了可以處理 GET 和 POST 請求。

  2. 方法參數:這個方法接受一個參數 String country,這是從前端表單傳遞過來的國家別。如果在請求中未傳遞國家別,則該參數將為 null

  3. 方法邏輯:在方法內部,首先檢查 country 參數是否為 null,如果是,則表示這是第一次請求,並且用戶尚未提交國家別查詢。在這種情況下,它將返回 "customersqrycountry",這個名稱通常對應於Thymeleaf模板視圖。

    如果 country 參數不是 null,則表示用戶已提交國家別查詢,該方法將在控制台中印出查詢的國家別,然後仍然返回 "customersqrycountry"。

總之,這個方法處理客戶查詢國家別的操作。如果國家別未提交,它將顯示查詢表單視圖,如果提交了國家別,則它會處理查詢,然後仍然顯示查詢表單視圖。

再測試看看:http://localhost:8080/customers/qry/country

後端回傳
https://ithelp.ithome.com.tw/upload/images/20231102/201190353zzPT59DHJ.png

https://ithelp.ithome.com.tw/upload/images/20231102/20119035jVHvgkCv4X.png
https://ithelp.ithome.com.tw/upload/images/20231105/20119035AtJJeNigau.png
接下來要裝:https://mvnrepository.com/search?q=spring+boot+jdbc

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-jdbc -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
    <version>3.0.0</version>
</dependency>

目前配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.0.12</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.tzu2</groupId>
	<artifactId>myweb2</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>myweb2</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>11</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-thymeleaf -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
    <version>3.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.31</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-jdbc -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
    <version>3.0.0</version>
</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

Spring Boot Starter Data JDBC

貼到系統設定

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jdbc/core/JdbcTemplate.html

修改ApplictionConfig並測試看看有沒有注入
@Bean //生命週期每一個注入 產生一個體
public JdbcTemplate createJdbcTemplate(DataSource datasource) {
//建構JdbcTemplate物件
System.out.println(“JdbcTemplate 注入的DataSource:”+datasource.toString());
JdbcTemplate template=new JdbcTemplate();
template.setDataSource(datasource); //Property Injection屬性注入依賴物件
return template;
}

package com.tzu.config;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;

import com.mysql.cj.jdbc.MysqlDataSource;
import com.tzu.beans.HelloBean;
import com.tzu.beans.HelloProxy;
import com.tzu.beans.IHello;
import com.tzu.beans.TWHello;

//透過方法生產Bean物件 註冊到Spring容器去
@Configuration
public class ApplictionConfig {
 //Attribute 使用spEL ${}
 //@Value標註取出預設組態application.properties設定項目
 @Value("${spring.datasource.url}")
 private String url;
 @Value("${spring.datasource.username}")
 private String userName;
 @Value("${spring.datasource.password}")
 private String password;
 
 public ApplictionConfig() {
  System.out.println("Configuration Bean配置了");
 }

 //生產一個HelloBean物件
 @Bean(name="hellonean")
 public HelloBean getHelloBean() {
  System.out.println("Hello Bean產生了");
  //建構HelloBean
  HelloBean hello=new HelloBean();
  return hello;
 }
 
 @Bean
 public TWHello getTWHello() {
  System.out.println("TW Hello Bean產生了");
  //建構HelloBean
  TWHello hello=new TWHello();
  return hello;
 }
 
 
 
 
 //參數使用定義Bean alias Name 注入依賴 隨著窗口物件注入到對方去 進行反轉物件注入
 @Bean
 public HelloProxy getHelloProxy(TWHello bean) {
  var helloProxy=new HelloProxy(bean);
  return helloProxy;
 }
 
 //產生一個DataSource 是共用的物件(連接物件工廠 整個應用系統工廠只要一個即可)
 @Bean
 public DataSource createDataSource() {
  System.out.println("Datasource:"+this.url);
  //建構MySQLDataSource
  MysqlDataSource datasource=new MysqlDataSource();
  //配置要件 URL/User name/password
  datasource.setUrl(url);
  datasource.setUser(userName);
  datasource.setPassword(password);
  
  //Driver 會進行內部使用
  return datasource;
 }
 //生產JdbcTemplate元件(Spring Bean)
  //透過IoC注入控制反轉 注入DataSource物件
  @Bean //生命週期每一個注入 產生一個體
  public JdbcTemplate createJdbcTemplate(DataSource datasource) {
   //建構JdbcTemplate物件
   System.out.println("JdbcTemplate 注入的DataSource:"+datasource.toString());
   JdbcTemplate template=new JdbcTemplate();
   template.setDataSource(datasource); //Property Injection屬性注入依賴物件
   return template;
  }
}

這段程式碼是一個Java Spring的配置檔案,主要用於設定和定義Spring應用程式中的bean和它們的相依性。以下是這段程式碼的主要內容:

  1. @Configuration:這個註解表示這個類別是Spring應用程式上下文的配置類別。它定義和配置Spring bean。

  2. @Value:這些註解用於將外部屬性檔案(通常是application.properties)中的值注入到相應的字段中。例如,@Value("${spring.datasource.url}")spring.datasource.url 的值注入到 url 字段中。

  3. @Bean:這些註解定義了方法,用來建立和配置Spring bean。這些方法由Spring容器調用,並返回的物件在應用程式上下文中被管理為bean。

  4. public ApplictionConfig():這是配置類別的建構函式。它在載入配置類別時執行,提供了一個印出當它被呼叫時的訊息。

  5. getHelloBean():這個方法定義一個名為 "hellonean" 的bean,並返回一個 HelloBean 物件。

  6. getTWHello():這個方法定義一個型別為 TWHello 的bean。

  7. getHelloProxy(TWHello bean):這個方法定義了一個名為 "helloProxy" 的bean,它依賴於一個 TWHello bean。它建立一個 HelloProxy 物件,使用提供的 TWHello bean。

  8. createDataSource():這個方法定義了一個用於DataSource(可能是MySQL資料庫)的bean。它根據從屬性檔案中擷取的URL、使用者名稱和密碼的值來配置資料來源。

  9. createJdbcTemplate(DataSource datasource):這個方法定義了一個JdbcTemplate的bean,這是用於資料庫訪問的Spring元件。它將之前定義的DataSource bean注入到JdbcTemplate中,並將其設置為一個屬性。

總結,這個配置檔案定義了幾個Spring bean,包括 HelloBeanTWHelloJdbcTemplate,並管理它們的相依性,如將資料來源注入到JdbcTemplate中。它還從外部的配置檔案讀取屬性,並使用這些值來配置bean,如資料來源的URL和認證資訊。

再加入@Scope(“singleton”)

package com.tzu.config;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.jdbc.core.JdbcTemplate;

import com.mysql.cj.jdbc.MysqlDataSource;
import com.tzu.beans.HelloBean;
import com.tzu.beans.HelloProxy;
import com.tzu.beans.IHello;
import com.tzu.beans.TWHello;

//透過方法生產Bean物件 註冊到Spring容器去
@Configuration
public class ApplictionConfig {
 //Attribute 使用spEL ${}
 //@Value標註取出預設組態application.properties設定項目
 @Value("${spring.datasource.url}")
 private String url;
 @Value("${spring.datasource.username}")
 private String userName;
 @Value("${spring.datasource.password}")
 private String password;
 
 public ApplictionConfig() {
  System.out.println("Configuration Bean配置了");
 }

 //生產一個HelloBean物件
 @Bean(name="hellonean")
 public HelloBean getHelloBean() {
  System.out.println("Hello Bean產生了");
  //建構HelloBean
  HelloBean hello=new HelloBean();
  return hello;
 }
 
 @Bean
 public TWHello getTWHello() {
  System.out.println("TW Hello Bean產生了");
  //建構HelloBean
  TWHello hello=new TWHello();
  return hello;
 }
 
 
 
 
 //參數使用定義Bean alias Name 注入依賴 隨著窗口物件注入到對方去 進行反轉物件注入
 @Bean
 public HelloProxy getHelloProxy(TWHello bean) {
  var helloProxy=new HelloProxy(bean);
  return helloProxy;
 }
 
 //產生一個DataSource 是共用的物件(連接物件工廠 整個應用系統工廠只要一個即可)
 @Bean
 @Scope("singleton")
 public DataSource createDataSource() {
  System.out.println("Datasource:"+this.url);
  //建構MySQLDataSource
  MysqlDataSource datasource=new MysqlDataSource();
  //配置要件 URL/User name/password
  datasource.setUrl(url);
  datasource.setUser(userName);
  datasource.setPassword(password);
  
  //Driver 會進行內部使用
  return datasource;
 }
 //生產JdbcTemplate元件(Spring Bean)
  //透過IoC注入控制反轉 注入DataSource物件
  @Bean //生命週期每一個注入 產生一個體
  public JdbcTemplate createJdbcTemplate(DataSource datasource) {
   //建構JdbcTemplate物件
   System.out.println("JdbcTemplate 注入的DataSource:"+datasource.toString());
   JdbcTemplate template=new JdbcTemplate();
   template.setDataSource(datasource); //Property Injection屬性注入依賴物件
   return template;
  }
}

這段程式碼仍然是一個Java Spring的配置檔案,但有一個小改變:在createDataSource()方法上使用了@Scope("singleton")註解,這表示DataSource bean 的作用範圍是單例(singleton)。這個設定將使Spring容器在應用程式生命週期中只建立一個DataSource bean,並在需要時重複使用它。

其他部分的功能和說明仍然相同,以下是對這段程式碼的主要內容的簡要說明:

  1. @Scope("singleton"):這個註解用於設定bean的作用範圍。在這個例子中,DataSource bean 的作用範圍被設定為singleton,這意味著只會有一個DataSource bean 實例存在於Spring容器中。

  2. createDataSource() 方法:這個方法仍然用於定義一個DataSource bean,但現在它是一個單例bean。這個bean用於建立資料庫連線,並配置URL、使用者名稱和密碼。

  3. createJdbcTemplate(DataSource datasource) 方法:這個方法定義了一個JdbcTemplate的bean,它仍然注入了之前定義的DataSource bean,但現在DataSource bean是單例。這個bean用於執行資料庫查詢。

總結,這個配置檔案主要是用來定義和配置Spring bean,並且在此版本中,DataSource bean 被設定為單例,以提高效能,並確保在應用程式中只有一個DataSource 實例。其他部分的功能和目的與之前的版本相同。

這時資料庫view先用sql語法測試

Select * From customer_list Where country='Taiwan'

再修改CustomersController插入@Autowired
private JdbcTemplate jdbcTemplate; //DataSource會注入控制反轉

package com.tzu.controllers;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping(path="/customers")
public class CustomersController {
 //Attribute(Data Field) Field Injection
 @Autowired
 private JdbcTemplate jdbcTemplate; //DataSource會注入控制反轉
 
 //查詢功能設計
 @RequestMapping(path="/qry/country",
   method= {RequestMethod.GET,RequestMethod.POST})
 public String customersQry(String country) {
  //是否第一次請求 沒有傳遞國家別
    if(country==null) {
     return "customersqrycountry"; //View Page名稱
    }else {
     System.out.println("查詢國家別:"+country);
     DataSource ds=jdbcTemplate.getDataSource();
     System.out.println(ds.toString());
  
  return "customersqrycountry";
}
 }
}

這段程式碼是一個Spring控制器(Controller),它處理Web應用程式的HTTP請求和回應。以下是對這段程式碼的主要內容的簡要說明:

  1. @Controller:這個註解表示這個類別是一個Spring MVC控制器,它會處理HTTP請求。

  2. @RequestMapping:這個註解用於定義控制器處理的HTTP請求路徑。在這個例子中,所有與"/customers"路徑相關的請求都將由這個控制器處理。

  3. @Autowired:這個註解用於依賴注入,它將jdbcTemplate 注入到這個控制器中。jdbcTemplate 是一個JdbcTemplate bean,它是用於執行資料庫查詢的Spring組件。

  4. customersQry 方法:這個方法處理對"/customers/qry/country"路徑的HTTP GET和POST請求。它接受一個名為country 的參數,用於查詢客戶資料。

    • 如果 country 參數是null,表示這是第一次請求,它將返回一個View Page的名稱 "customersqrycountry",這個View Page將用於輸入國家別的查詢。

    • 如果 country 參數不是null,表示已經傳遞了國家別,它會顯示查詢的國家別,並且透過 jdbcTemplate 取得資料庫連線物件 DataSource,然後將它印出來。

  5. 這個控制器主要用於處理客戶資料的查詢,並且它依賴於jdbcTemplate,這個jdbcTemplate 是透過控制反轉(IoC)由Spring容器注入的。

總結,這個控制器處理與"/customers/qry/country"路徑相關的HTTP請求,並使用Spring的依賴注入功能,將jdbcTemplate 注入到控制器中,以便在方法中執行資料庫查詢。

再用客戶資料查詢http://localhost:8080/customers/qry/country 測試

產生的樣子:

再增加一個檔案Customer.java

package com.tzu.domain;
//JavaBean 封裝每一筆客戶資料 
public class Customer implements java.io.Serializable {
 //Attribute
 private short id;
 private String name;
 private String address;
 private String phone;
 private String country;
 public short getId() {
  return id;
 }
 public void setId(short id) {
  this.id = id;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String getAddress() {
  return address;
 }
 public void setAddress(String address) {
  this.address = address;
 }
 public String getPhone() {
  return phone;
 }
 public void setPhone(String phone) {
  this.phone = phone;
 }
 public String getCountry() {
  return country;
 }
 public void setCountry(String country) {
  this.country = country;
 }

}

這段程式碼定義了一個JavaBean,稱為 Customer,用於封裝客戶資料。以下是 Customer 類別的主要特點:

  1. Customer 類別實作了 java.io.Serializable 介面,這表示它可以被序列化,通常用於將物件轉換成位元組以便於儲存或傳輸。

  2. Customer 類別具有一些私有(private)屬性,這些屬性用於存儲客戶資料,包括:

    • id(短整數):客戶的唯一識別符。
    • name(字串):客戶的名稱。
    • address(字串):客戶的地址。
    • phone(字串):客戶的電話號碼。
    • country(字串):客戶的國家。
  3. 對於每個屬性,都有一個公開的getter(取值方法)和setter(設值方法)方法,用於訪問和設置相應的屬性值。這遵循了JavaBean的標準約定,讓外部程式可以存取和修改這些屬性。

這個 Customer 類別用於封裝客戶資料,允許您創建 Customer 物件,並設置或檢索相關的客戶資訊。這樣的JavaBean常常在應用程式中用於儲存和處理資料。

再更改CustomersController

package com.tzu.controllers;

import java.util.List;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.tzu.domain.Customer;

@Controller
@RequestMapping(path="/customers")
public class CustomersController {
 //Attribute(Data Field) Field Injection
 @Autowired
 private JdbcTemplate jdbcTemplate; //DataSource會注入控制反轉
 
 //查詢功能設計
 @RequestMapping(path="/qry/country",
   method= {RequestMethod.GET,RequestMethod.POST})
 public String customersQry(String country) {
  //是否第一次請求 沒有傳遞國家別
    if(country==null) {
     return "customersqrycountry"; //View Page名稱
    }else {
     System.out.println("查詢國家別:"+country);
     DataSource ds=jdbcTemplate.getDataSource();
     System.out.println(ds.toString());  
     //1.採用DAO設計模式(Spring Boot data jdbc)
     String sql="SELECT ID,name,address,phone,country "
       + "FROM sakila.customer_list where country=?";
     //2.進行國家別相關客戶查詢
     List<Customer> result=jdbcTemplate.query(sql,
       //傳遞一個程序當作參數(RowMapper/maprow 介面) 使用Lambda 
       //查詢符合每一筆 逐筆傳遞進來callback 自訂程序封裝結果
       (rs,num)->{
        //將相對紀錄封裝成自訂JavaBean-Customer
        Customer customer=new Customer();
        //注入相對記錄欄位於JavaBean物件中
        customer.setId(rs.getShort("ID"));
        customer.setName(rs.getString("name"));
        customer.setAddress(rs.getString("address"));
        customer.setPhone(rs.getString("phone"));
        customer.setCountry(rs.getString("country"));
        return customer;
       },
       country
       );
     System.out.println("查詢結果:"+result.size());
  return "customersqrycountry";
}
 }
}

這段程式碼是一個Spring控制器(Controller),用於處理客戶資料的查詢功能。以下是對這段程式碼的主要內容的簡要說明:

  1. @Controller:這個註解表示這個類別是一個Spring MVC控制器,它會處理HTTP請求。

  2. @RequestMapping:這個註解用於定義控制器處理的HTTP請求路徑。在這個例子中,所有與"/customers"路徑相關的請求都將由這個控制器處理。

  3. @Autowired:這個註解用於依賴注入,它將jdbcTemplate 注入到這個控制器中。jdbcTemplate 是一個JdbcTemplate bean,它用於執行資料庫查詢。

  4. customersQry 方法:這個方法處理對"/customers/qry/country"路徑的HTTP GET和POST請求。它接受一個名為country 的參數,用於查詢客戶資料。

    • 如果 country 參數是null,表示這是第一次請求,它將返回一個View Page的名稱 "customersqrycountry",這個View Page將用於輸入國家別的查詢。

    • 如果 country 參數不是null,表示已經傳遞了國家別,它會顯示查詢的國家別,然後執行資料庫查詢操作:

      • 定義SQL查詢語句,並將country 參數作為查詢的條件。

      • 使用 jdbcTemplate.query() 方法執行查詢,並將查詢結果封裝成 Customer 物件的清單。這是透過傳遞一個Lambda表示式給 jdbcTemplate.query(),用於將查詢結果的每一筆記錄對映到一個 Customer 物件中。

      • 最後,將查詢結果的大小印出。

這個控制器的主要功能是根據輸入的國家別查詢客戶資料,並且使用Spring的依賴注入功能,將jdbcTemplate 注入到控制器中,以便執行資料庫查詢。查詢結果是通過將每一條記錄對映到 Customer 物件中,然後放入結果列表中。

測試查出幾筆是Taiwan資料http://localhost:8080/customers/qry/country

https://ithelp.ithome.com.tw/upload/images/20231105/2011903533tFXIzV1s.png

謝謝收看/images/emoticon/emoticon41.gif


上一篇
Springboot~開始使用資料庫
下一篇
Springboot~從畫面顯示筆數~
系列文
自己開發一個~?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言